package util

import (
	"context"
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/coreos/etcd/clientv3"
)

const (
	USER     = "weixin_monitor_owl"
	PASSWORD = "B8CE9A70FCEA17E31DF4141BFD40ED35"
)

type AuthKey struct {
	User       string `json:"user"`
	CreateTime string `json:"createTime"`
	//Password   string `json:"password"`
}

func Assert(expr bool, err string) {
	if expr {
		panic(err)
	}

	return
}

func GetAuth() string {

	create := fmt.Sprintf("%d", int(time.Now().UnixNano()/1000000))
	auth := &AuthKey{
		User:       USER,
		CreateTime: create,
	}

	data, _ := json.Marshal(auth)
	encodeString := base64.StdEncoding.EncodeToString(data)
	pHash := fmt.Sprintf("%x", md5.Sum([]byte(PASSWORD)))
	key := fmt.Sprintf("%x", md5.Sum([]byte(encodeString+pHash)))

	return fmt.Sprintf("%s:%s", key, encodeString)

}

var (
	OWLServiceList = make(map[int]string, 0)
	OWLMu          = new(sync.Mutex)
)

func CopyMap(src map[int]string, dst map[int]string, mu *sync.Mutex) bool {
	mu.Lock()
	defer mu.Unlock()

	if len(dst) == 0 {
		return false
	}

	for k, v := range dst {
		src[k] = v
	}

	return true
}

func GetOWLServicesList(url string) (map[int]string, error) {
	client := &http.Client{}
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}

	request.Header.Add("Authorization", GetAuth())

	resp, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("http status code:%d", resp.StatusCode)
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	res := make(map[int]string, 0)
	if string(body) == "" {
		if CopyMap(res, OWLServiceList, OWLMu) == false {
			return nil, fmt.Errorf("body is empty")
		}
		return res, nil
	}

	hmap := make(map[string]interface{}, 0)
	err = json.Unmarshal(body, &hmap)
	if err != nil {
		return nil, fmt.Errorf("%s, body:%s", err.Error(), string(body))
	}

	if _, ok := hmap["data"]; ok {
		detail := hmap["data"].([]interface{})
		for _, item := range detail {
			m := item.(map[string]interface{})
			id := int(m["id"].(float64))
			name := m["name"].(string)
			siteShow := int(m["sitesShow"].(float64))
			if siteShow == 1 {
				res[id] = name
			}
		}
	}

	CopyMap(OWLServiceList, res, OWLMu)

	return res, nil
}

func GetRPCServicesList(etcd string) (map[string]bool, error) {

	etcdList := strings.Split(etcd, ",")
	if len(etcdList) == 0 {
		return nil, errors.New("etcd address miss")
	}
	etcdClient, err := clientv3.New(
		clientv3.Config{
			Endpoints:        etcdList,
			AutoSyncInterval: time.Second * 30,
		})
	if err != nil {
		return nil, err
	}
	defer etcdClient.Close()

	resp, err := etcdClient.Get(context.TODO(), "lark.address.0", clientv3.WithRange("lark.address.zzzzzzzzzzzzzzzzzzzzz"))
	if err != nil {
		return nil, err
	}

	lst := make(map[string]bool, 0)
	for _, item := range resp.Kvs {
		a := strings.Split(string(item.Key), ".")
		if len(a) >= 3 {
			lst[a[2]] = true
		}
	}

	lst["wing-service"] = true
	lst["erp-service"] = true
	lst["global-service"] = true
	lst["koubei-service"] = true
	lst["meidian_crm_service"] = true
	//	lst["cart"] = true

	return lst, nil
}
